# -*- encoding: utf-8 -*-
"""
@File    : auto_test_v1.0.py
@Time    : 2020/1/8 14:37
@Author  : Doris
"""
import configparser
import time
import xml.etree.ElementTree as ET
import os

from bs4 import BeautifulSoup

# 全局变量，api计数
x = 1

# 当前文件路径
CURRENT_PATH = os.getcwd ()
# 地址末尾没有倒斜杆，==>>>D:\WORKPLACE\jmeterTest\Version1.0
print(CURRENT_PATH)


#  方法：获取当前时间，用于命名
def getDateTime():
    '''
    获取当前日期时间，格式'20150708_085159'
    '''
    return time.strftime(r'%Y%m%d_%H%M%S-', time.localtime(time.time()))


# 获取当前时间用于生成报告文件夹
begin = getDateTime()

# jmx生成路径
JMX_API_PATH = CURRENT_PATH + "\\api_jmx\\"

# 测试报告存放地址(需要目录存在）
REPORT_PATH = CURRENT_PATH + "\\report\\" + begin + "report\\"

# 测试结果地址(需要目录存在）
RESULT_PATH = CURRENT_PATH + "\\result\\" + begin + "result\\"

htmlreport_list = []
jmxfile_name_list = []

# 报告汇总v1.0，拼html语句
# 之后改bs4啦
head = '<!DOCTYPE html><html lang="en"><head><title>报告汇总主页</title></head><body><div ' \
       'name="reportTable" style="text-align: center"><table border="1" style="margin: auto"> '
end = '</table></div></body></html>'

# 方法：检查路径是否存在
# 不存在就新建
def checkPath(path):
    if os.path.exists(path):
        pass
    else:
        os.makedirs(path)


# 方法：读取并从模板中编辑生成JMX文件
def editJMX(jmxFile, ip, port, path, param, loops, num_threads, ramp_time):
    tree = ET.parse (jmxFile)
    root = tree.getroot ()  # Reading the file from disk

    # 获取要修改的标签
    s_loop = root.find (".//*[@name='LoopController.loops']")
    s_num_threads = root.find (".//*[@name='ThreadGroup.num_threads']")
    s_ramp_time = root.find (".//*[@name='ThreadGroup.ramp_time']")
    s_domain = root.find (".//*[@name='HTTPSampler.domain']")
    s_port = root.find (".//*[@name='HTTPSampler.port']")
    s_path = root.find (".//*[@name='HTTPSampler.path']")
    s_param = root.find (".//*[@name='Argument.value']")

    # 修改标签内容
    s_domain.text = str (ip)
    s_port.text = str (port)
    s_path.text = str (path)
    s_param.text = str (param)
    s_loop.text = str (loops)
    s_num_threads.text = str (num_threads)
    s_ramp_time.text = str (ramp_time)
    tree.write (CURRENT_PATH + '/api_jmx/api' + str (x) + '.jmx')  # 只能用加号，逗号出错


# 方法：拆分一行api数据
# 主机/路径/参数
def splitData(data):
    host, path, data = data.split ('$', 2)  # 以$分割两次
    ip, port = host.split (':', 1)  # 以:分割一次
    return ip, port, path, data


# 方法：执行命令行运行jmx非GUI界面脚本测试
def excuteJMX():
    for n in range (1, x):
        now = getDateTime() # 获取当前时间
        api_name = "api" + str (n)  # api的名字
        name = now + api_name   # 报告结果名
        # 执行jmx
        run ="jmeter -n -t " + JMX_API_PATH + api_name + ".jmx"
        # run = JMETER_BAT_Home + " -n -t " + JMX_API_PATH + api_name + ".jmx"
        # 生成并存储测试结果和报告
        generate_result = " -l" + RESULT_PATH + name + "_result.jsl -e -o " + REPORT_PATH + name
        cmd = run + generate_result
        os.system (cmd)


# 方法：生成报告汇总html页面
def createHtml(htmlFile):
    print("报告文件夹是：",REPORT_PATH)
    # 1.获取报告文件夹内容,目录名
    for root, dirs, files in os.walk (REPORT_PATH):
        break   # 获取第一子目录列表
    print (dirs)

    # 2.整理html内容
    # 2.1 设置标题<th>
    title = ['执行时间', 'jmx文件', '响应结果', '报告详情']
    # 标题行
    th_str = '<tr name="title">'
    for x in title:
        th_str = th_str + '<th>' + x + '</th>'
    else:
        th_str = th_str + '</tr>'

    # 文件夹列表长度（个数）
    length = len (dirs)
    print ("==>>文件夹长度（个数）：", length, "\n================")

    # ==>>那么有问题了，同一个文件夹，把之前的报告也读了，要处理
    # 每次都新建文件夹，以测试时间为文件名，包含这次所有报告

    # 2.2 设置每个api报告链接内容<td>
    # 构建报告链接,格式举例如下，进行地址拼接
    # D:\WORKPLACE\jmeterTest\Version1.0\report\20200110_094242-report\20200110_094242-api1
    # REPORT_PATH + folderName + '\\' + index.html(记得加斜杠分隔符）
    # REPORT_PATH = D:\WORKPLACE\jmeterTest\Version1.0\report\20200110_094242-report\
    # folderName = 20200110_094242-api1

    # 初始化列表主题行内容
    report_td = ''

    # 把报告内文件夹名字设为【date-api】，用-分割
    for folderName in dirs:
        report_td += '<tr>'
        print ("==>>文件夹名称:", folderName)
        # 1)执行时间
        time, apiName = folderName.split ('-')
        print ("==>>>创建时间:", time)
        report_td += '<td>' + time + '</td>'
        # 2)jmx文件
        print ("==>>>api名称:", apiName)
        report_td += '<td><a href="' + JMX_API_PATH + apiName + '.jmx" target="_blank">' + apiName + '</a></td>'
        print ("==>>api文件地址：", JMX_API_PATH + apiName)

        # 3)响应结果jls
        report_td += '<td><a href="' + RESULT_PATH + time + '-' + apiName + '_result.jsl" target="_blank">' + time + apiName + '_result.jsl</a></td>'
        print ("==>>jsl文件地址：", RESULT_PATH + time + '-' + apiName + '_result.jsl')

        # 4)报告详情
        report_td += '<td><a href="' + REPORT_PATH + folderName + '\\index.html" target="_blank">查看</a></td>'
        print ("==>>index.html文件地址：", REPORT_PATH + folderName + '\\index.html')
        report_td += "</tr>"

    print ("报告汇总在本次生成报告文件夹下面：", REPORT_PATH + begin + 'SummaryReport.html')
    htmlDemo = open (htmlFile, 'w')  # w-覆盖写，a-末尾追加写
    htmlDemo.write (head + th_str + report_td + end)
    htmlDemo.close ()


# 执行主入口
if __name__ == '__main__':
    # 〇、检查路径是否存在（不存在则新增）
    checkPath(JMX_API_PATH)
    checkPath (REPORT_PATH)
    checkPath (RESULT_PATH)

    # 一、读配置文件settings.ini
    cf = configparser.ConfigParser ()
    cf.read (CURRENT_PATH + '/settings.ini', encoding='UTF-8')

    # 1.线程配置内容(read int)
    number_of_threads = cf.getint ("common_set", "number_of_threads")
    ramp_up_period = cf.getint ("common_set", "ramp_up_period")
    loop_count = cf.getint ("common_set", "loop_count")

    # 2.接口数据地址
    api_path = cf.get ("api_path", "api_data")
    print ('api详情文件名：', api_path)

    api_cf = configparser.ConfigParser ()
    api_cf.read (CURRENT_PATH + "/" +api_path)

    # 二、读取api配置详情
    api_cf = configparser.ConfigParser ()
    # api_cf.read (api_path, encoding="UTF-8")
    api_cf.read (api_path)
    # 获取每行api详情
    for item in api_cf["api_test"]:
        api_data = api_cf.get ("api_test", item)
        ip, port, path, data = splitData (api_data)
        # 三、编辑JMX文件
        jmxName = CURRENT_PATH + '/api_jmx/api_demo.jmx'
        editJMX (jmxName, ip, port, path, data, loop_count, number_of_threads, ramp_up_period)
        x += 1
        # print (x)

    # 四、执行JMX
    excuteJMX ()

    # 五、生成报告汇总html
    print("报告汇总地址：", REPORT_PATH + begin + 'SummaryReport.html')
    createHtml(REPORT_PATH + begin + 'SummaryReport.html')
